/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session.TX;

import java.util.ArrayList;
import java.util.List;
import javax.ejb.Remove;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import entity.*;
import Helper.Helper_FoodItemSearch;
import Helper.Helper_OutletFoodItem;
import java.util.HashSet;

/**
 *
 * @author AdminNUS, Lu Xiaodi
 */
@Stateless
public class DishManagerSB implements DishManagerSBRemote {

    @PersistenceContext
    private EntityManager em;

    public DishManagerSB() {
    }

    public void addFoodItem(Long outletId, String dishName, String description,
            Double cost, String type, String pathName) {

        type = type.trim();
        if (!(type.equalsIgnoreCase("Menu Item")
                || type.equalsIgnoreCase("Featured Dish")
                || type.equalsIgnoreCase("Promotional Item")
                || type.equalsIgnoreCase("Festive Item"))) {
            // throw dish type not exist exception
            return;
        }

        FoodItem fc = new FoodItem();
        Outlet out = em.find(Outlet.class, outletId);
        if (out == null) {//throw existexception
        } else {
            fc.setName(dishName);
            fc.setDescription(description);
            fc.setPrice(cost);
            fc.setType(type);
            fc.setLocked(false);
            fc.setPathName(pathName);
            fc.setOutletId(outletId);
            fc.setStakeholderName(out.getStakeholder().getName());
            out.addFoodItem(fc);
            em.persist(fc);
            em.persist(out);
        }
    }

    public void deleteFoodItem(Long foodID, Long outletId) {

        FoodItem fc = em.find(FoodItem.class, foodID);
        if (fc == null) {
            //nothing to delete
        } else {
            Outlet out = em.find(Outlet.class, outletId);
            if (out == null) {
                //throw existexception}
            } else if (!out.getFoodMenu().contains(fc)) {
                //throw exception
            }
            out.removeFoodItem(fc);
            em.remove(fc);
            em.persist(out);
        }
    }

    public boolean editFoodItem(FoodItem item) {
        return this.editFoodItem(item.getId(), item.getName(), item.getDescription(), item.getPrice());
    }

    public boolean editFoodItem(Long id, String dishName, String description, Double cost) {
        FoodItem fi = em.find(FoodItem.class, id);
        if (fi == null) //throw exist exception
        {
            return false;
        } else {
            fi.setName(dishName);
            fi.setDescription(description);
            fi.setPrice(cost);
            em.persist(fi);
        }
        return true;
    }

    private List<FoodItem> searchFoodItemForSaleByName(String name) {
        List<FoodItem> returnList = new ArrayList<FoodItem>();
        name = "%" + name.toLowerCase().trim().replace(" ", "%") + "%";
        Query query = em.createQuery("SELECT f FROM FoodItem f WHERE f.name LIKE :value1 AND "
                + "f.locked = :value2 AND f.type = :value3 ORDER BY f.name, f.stakeholderName, f.type DESC");
        query.setParameter("value1", name);
        query.setParameter("value2", false);
        query.setParameter("value3", "Festive Item");
        returnList.addAll(query.getResultList());
        query.setParameter("value3", "Promotional Item");
        returnList.addAll(query.getResultList());
        query.setParameter("value3", "Featured Dish");
        returnList.addAll(query.getResultList());
        return returnList;
    }

    public List<Helper_FoodItemSearch> searchFoodItemHelperByName(String name) {
        List<FoodItem> resultList = this.searchFoodItemForSaleByName(name);
        if (resultList == null) {
            return null;
        } else if (resultList.size() == 0) {
            return new ArrayList<Helper_FoodItemSearch>();
        }

        //initialize return items
        List<Helper_FoodItemSearch> searchResult = new ArrayList<Helper_FoodItemSearch>();
        FoodItem stakeholderItem = resultList.get(0);
        Helper_FoodItemSearch searchHelper = new Helper_FoodItemSearch(
                stakeholderItem.getName(), stakeholderItem.getStakeholderName(), stakeholderItem.getPathName());
        //loop to get all food items for sale, which means they are not of menu item type
        //(group by stakeholder name)
        for (int i = 0; i < resultList.size(); i++) {
            FoodItem current = resultList.get(i);
            if (!(current.getStakeholderName().equals(stakeholderItem.getStakeholderName())
                    && current.getName().equals(stakeholderItem.getName()))) {
                searchResult.add(searchHelper);
                stakeholderItem = resultList.get(i);
                searchHelper = new Helper_FoodItemSearch(stakeholderItem.getName(),
                        stakeholderItem.getStakeholderName(), stakeholderItem.getPathName());
            }
            Outlet out = em.find(Outlet.class, current.getOutletId());
            Helper_OutletFoodItem containingItem =
                    new Helper_OutletFoodItem(out.getId(), out.getOutletName(), out.getPhoneNumber(),
                    current.getId(), current.getName(), current.getStakeholderName(),
                    current.getDescription(), current.getPrice(), current.getType(),
                    current.getPathName(), out.getAddress());
            searchHelper.addOutletItem(containingItem);
            if (i == resultList.size() - 1) {
                searchResult.add(searchHelper);
            }
        }
        return searchResult;
    }

    public void addCuisine(String cuisineName) {

        Cuisine c = new Cuisine();
        c.setCuisineName(cuisineName);

        em.persist(c);
    }

    public void deleteCuisine(String name) {

        Query q1 = em.createQuery("SELECT c FROM Cuisine c");

        for (Object o : q1.getResultList()) {
            Cuisine c = (Cuisine) o;
            if (c.getCuisineName().equals(name)) {
                em.remove(c);
                System.out.println("SERVER SIDE: entity with keyword " + name + " was found and deleted");
                break;
            }
        }
    }

    public List<FoodItem> getOutletFoodMenu(Long outletId) {
        Outlet out = em.find(Outlet.class, outletId);
        if (out == null) {
            return null;
        }
        List<FoodItem> returnList = new ArrayList<FoodItem>();
        for (FoodItem fi : out.getFoodMenu()) {
            returnList.add(fi);
        }
        return returnList;
    }

    private FoodItem getFoodItem(Outlet outlet, Long dishId) {
        List<FoodItem> dishes = outlet.getFoodMenu();
        for (FoodItem f : dishes) {
            if (f.getId() == dishId) {
                return f;
            }
        }
        return null;
    }

    // start ReservationManagementBean
    public List<FoodItem> getNonDeliItemForSale(Long outletId) {
        if (outletId == null) {
            return null;
        }
        Outlet oe = em.find(Outlet.class, outletId);
        if (oe == null) {
            return null;
        }
        ArrayList<FoodItem> returnList = new ArrayList<FoodItem>();
        for (Object o : oe.getFoodMenu()) {
            FoodItem foodItem = (FoodItem) o;
            if (foodItem.getType().equalsIgnoreCase("Festive Item")) {
                returnList.add(foodItem);
            }
        }
        for (Object o : oe.getFoodMenu()) {
            FoodItem foodItem = (FoodItem) o;
            if (foodItem.getType().equalsIgnoreCase("Promotional Item")) {
                returnList.add(foodItem);
            }
        }
        for (Object o : oe.getFoodMenu()) {
            FoodItem foodItem = (FoodItem) o;
            if (foodItem.getType().equalsIgnoreCase("Featured Dish")) {
                returnList.add(foodItem);
            }
        }
        return returnList;
    }

    public List<Helper_OutletFoodItem> getNonDeliItemHelperForSale(Long outletId) {
        if (outletId == null) {
            return null;
        }
        Outlet oe = em.find(Outlet.class, outletId);
        if (oe == null) {
            return null;
        }
        ArrayList<Helper_OutletFoodItem> returnList = new ArrayList<Helper_OutletFoodItem>();
        for (Object o : oe.getFoodMenu()) {
            FoodItem foodItem = (FoodItem) o;
            if (foodItem.getType().equalsIgnoreCase("Festive Item")) {
                Outlet out = em.find(Outlet.class, foodItem.getOutletId());
                if (out == null) {
                    //throw foodItemFormat exception
                }
                returnList.add(new Helper_OutletFoodItem(foodItem.getOutletId(), out.getOutletName(),
                        out.getPhoneNumber(), foodItem.getId(), foodItem.getName(),
                        foodItem.getStakeholderName(), foodItem.getDescription(), foodItem.getPrice(),
                        foodItem.getType(), foodItem.getPathName(), out.getAddress()));
            }
        }
        for (Object o : oe.getFoodMenu()) {
            FoodItem foodItem = (FoodItem) o;
            if (foodItem.getType().equalsIgnoreCase("Promotional Item")) {
                Outlet out = em.find(Outlet.class, foodItem.getOutletId());
                if (out == null) {
                    //throw foodItemFormat exception
                }
                returnList.add(new Helper_OutletFoodItem(foodItem.getOutletId(), out.getOutletName(),
                        out.getPhoneNumber(), foodItem.getId(), foodItem.getName(),
                        foodItem.getStakeholderName(), foodItem.getDescription(), foodItem.getPrice(),
                        foodItem.getType(), foodItem.getPathName(), out.getAddress()));
            }
        }
        for (Object o : oe.getFoodMenu()) {
            FoodItem foodItem = (FoodItem) o;
            if (foodItem.getType().equalsIgnoreCase("Featured Dish")) {
                Outlet out = em.find(Outlet.class, foodItem.getOutletId());
                if (out == null) {
                    //throw foodItemFormat exception
                }
                returnList.add(new Helper_OutletFoodItem(foodItem.getOutletId(), out.getOutletName(),
                        out.getPhoneNumber(), foodItem.getId(), foodItem.getName(),
                        foodItem.getStakeholderName(), foodItem.getDescription(), foodItem.getPrice(),
                        foodItem.getType(), foodItem.getPathName(), out.getAddress()));
            }
        }
        return returnList;
    }

    public List<Helper_OutletFoodItem> getFestiveItemsHelper(Long outletId) {
        List<FoodItem> festiveEntity = this.getFestiveItems(outletId);
        ArrayList<Helper_OutletFoodItem> returnList = new ArrayList<Helper_OutletFoodItem>();
        for (FoodItem foodItem : festiveEntity) {
            Outlet out = em.find(Outlet.class, foodItem.getOutletId());
            if (out == null) {
                //throw foodItemFormat exception
            }
            returnList.add(new Helper_OutletFoodItem(foodItem.getOutletId(), out.getOutletName(),
                    out.getPhoneNumber(), foodItem.getId(), foodItem.getName(),
                    foodItem.getStakeholderName(), foodItem.getDescription(), foodItem.getPrice(),
                    foodItem.getType(), foodItem.getPathName(), out.getAddress()));
        }
        return returnList;
    }

    private List<FoodItem> getFestiveItems(Long outletId) {
        Outlet oe = em.find(Outlet.class, outletId);
        if (oe == null) {
            return null;
        }
        List<FoodItem> festiveList = new ArrayList<FoodItem>();
        for (FoodItem fc : oe.getFoodMenu()) {
            if (fc.getType().equalsIgnoreCase("Festive Item")) {
                festiveList.add(fc);
            }
        }
        return festiveList;
    }

    // ended ReservationManagementBean
    public void lockFoodItem(Long id) {
        FoodItem fc = em.find(FoodItem.class, id);
        if (fc == null) {
            return;
        }
        fc.setLocked(true);
        em.persist(fc);
    }

    public HashSet<String> getOutletWithDish(String dishKeyword) {

        HashSet returnSet = new HashSet<Long>();
        String foodName;
        //to enforce case insensitivity, set to uppercase
        dishKeyword.toUpperCase();

        Query q1 = em.createQuery("SELECT c FROM Outlet c");

        for (Object o : q1.getResultList()) {
            Outlet outlet = (Outlet) o;

            List<FoodItem> alaCarteList = outlet.getFoodMenu();

            for (FoodItem f : alaCarteList) {
                foodName = f.getName().toUpperCase();
                if (foodName.contains(dishKeyword)) {
                    returnSet.add(outlet.getId());
                    break;
                }
            }
        }
        return returnSet;
    }

    private List<FoodItem> getTheFoodList(ArrayList<Long> foodlistID) {
        List<FoodItem> foodlist = new ArrayList<FoodItem>();

        for (int i = 0; i < foodlistID.size(); i++) {
            FoodItem fi = em.find(FoodItem.class, foodlistID.get(i));
            if (fi != null) {
                foodlist.add(fi);
            }
        }

        return foodlist;
    }

    private Outlet getOutlet(Long outletId) {
        Outlet outlet = em.find(Outlet.class, outletId);
        return outlet;
    }

    @Remove
    public void remove() {
        System.out.println("DishManagerBean:remove()");
    }

    public List<FoodItem> getAllPromotionalDishes() {
        Query query = em.createQuery("select f from FoodItemAlaCarte As f where f.type= :value");
        query.setParameter("value", "Promotional Item");
        return query.getResultList();
    }

    public void unlockFoodItem(Long dishId) {
        FoodItem fc = em.find(FoodItem.class, dishId);
        if (fc == null) {
            return;
        }
        fc.setLocked(false);
        em.persist(fc);
    }
}
